
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>k8s 带你一步步 创建用户账号(User Account)</title>
            </head>
            <body>
            <a href="https://andyoung.blog.csdn.net">原作者博客</a>
            <div id="content_views" class="markdown_views prism-atom-one-light">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <p>RBAC官方文档： <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" rel="nofollow">https://kubernetes.io/docs/reference/access-authn-authz/rbac/</a><br> [k8s] 第九章 安全认证 <a href="https://andyoung.blog.csdn.net/article/details/120147986" rel="nofollow">https://andyoung.blog.csdn.net/article/details/120147986</a></p> 
<h3><a id="_2"></a>前言</h3> 
<ol><li> <p>RBAC (Role-Based Access Control，基于角色的访问控制）是一种新型、灵活且使用广泛的访问控制机制，它将权限授予“角色”（role）之上，这一点有别于传统访问控制机制中 将权限直接赋予使用者的方式，简单点来说就是将权限绑定到role中，然后用户和role绑定，这样用户就拥有了和role一样的权限。</p> </li><li> <p>在任何将资源或服务提供给有限使用者的系统上，认证和授权都是两个必不可少的功 能，认证用于身份鉴别，而授权则实现权限分派 。 Kubemetes 以插件化的方式实现了这两种 功能，且分别存在多种可用的插件。 另外，它还支持准入控制机制，用于补充授权机制以实现更精细的访问控制功能 。</p> </li><li> <p>API Server 作为 Kubernetes 集群系统的网关，是访问及管理资源对象的唯一人口，所有需要访问集群资源的组件，以及此前使用的 kubectl 命令等都要经由此网关进行集群访问和管理。</p> </li><li> <p>RBAC使用rbac.authorization.k8s.io API Group 来实现授权决策，允许管理员通过 Kubernetes API 动态配置策略，要启用RBAC，需要在 apiserver 中添加参数–authorization-mode=RBAC，如果使用的kubeadm安装的集群，都默认开启了RBAC，可以通过查看 Master 节点上 apiserver 的静态Pod定义文件：</p> <pre><code>[root@node-01 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml 
···

   - --authorization-mode=Node,RBAC
···
</code></pre> 
  <ol start="5"><li>如果是二进制的方式搭建的集群，添加这个参数过后，记得要重启 apiserver 服务。</li></ol> </li></ol> 
<h3><a id="RBAC_API_24"></a>RBAC API资源对象</h3> 
<p>Kubernetes有一个很基本的特性就是它的所有资源对象都是模型化的 API 对象，允许执行增、删、改、查等操作，比如下面的这下资源：</p> 
<ul><li> <p>Pods</p> </li><li> <p>ConfigMaps</p> </li><li> <p>Deployments</p> </li><li> <p>Nodes</p> </li><li> <p>Secrets</p> </li><li> <p>Namespaces<br> 上面这些资源对象的可能存在的操作有：</p> </li><li> <p>create</p> </li><li> <p>get</p> </li><li> <p>delete</p> </li><li> <p>list</p> </li><li> <p>update</p> </li><li> <p>edit</p> </li><li> <p>watch</p> </li><li> <p>exec</p> </li></ul> 
<h3><a id="_45"></a>用户账户和用户组</h3> 
<p>Kubernetes 并不会存储由认证插件从客户端请求中提取出的用户及所属组的信息，它们仅仅用于检验用户是否有权限执行其所请求的操作。</p> 
<p>客户端访问API服务的途径通常有三种：kubectl、客户端库或者直接使用 REST接口进行请求。</p> 
<p>而可以执行此类请求的主体也被 Kubernetes 分为两类：现实中的“人”和 Pod 对象， 它们的用户身份分别对应于常规用户 (User Account ）和服务账号 （ Service Account） 。</p> 
<ul><li> <p>Use Account（用户账号）：一般是指由独立于Kubernetes之外的其他服务管理的用 户账号，例如由管理员分发的密钥、Keystone一类的用户存储（账号库）、甚至是包 含有用户名和密码列表的文件等。Kubernetes中不存在表示此类用户账号的对象， 因此不能被直接添加进 Kubernetes 系统中 。</p> </li><li> <p>Service Account（服务账号）：是指由Kubernetes API 管理的账号，用于为Pod 之中的服务进程在访问Kubernetes API时提供身份标识（ identity ） 。Service Account通常要绑定于特定的命名空间，它们由 API Server 创建，或者通过 API 调用于动创建 ，附带着一组存储为Secret的用于访问API Server的凭据。</p> </li></ul> 
<p>Kubernetes 有着以下几个内建的用于特殊目的的组 。</p> 
<ul><li>system:unauthenticated ：未能通过任何一个授权插件检验的账号，即未通过认证测 试的用户所属的组 。</li><li>system :authenticated ：认证成功后的用户自动加入的一个组，用于快捷引用所有正常通过认证的用户账号。</li><li>system : serviceaccounts ：当前系统上的所有 Service Account 对象。</li><li>system :serviceaccounts :</li></ul> 
<h4><a id="RoleClusterRole_66"></a>Role和ClusterRole</h4> 
<ul><li> <p>Role是只作用于命名空间级别的，用于定义命名空间内资源权限集合。</p> </li><li> <p>ClusterRole则用于集群级别的资源权限集合，它们都是标准的 API 资源类型 。</p> </li><li> <p>一般来说， ClusterRole 的许可授权作用于整个集群，因此常用于控制 Role 无法生效的资源类型，这包括集群级别的资源（如Nodes）、非资源类型的端点（如／healthz）和作用于所有命名空间的资源（例如跨命名空间获取任何资源的权限）。</p> </li></ul> 
<h4><a id="RoleBindingClusterRoleBinding_74"></a>RoleBinding和ClusterRoleBinding</h4> 
<ul><li> <p>RoleBinding用于将Role上的许可权限绑定到一个或一组用户之上，它隶属于且仅能作用于一个命名空间。绑定时，可以引用同一名称中的Role，也可以引用集群级别的 ClusterRole。</p> </li><li> <p>ClusterRoleBinding则把ClusterRole中定义的许可权限绑定在一个或一组用户之上，它仅可以引用集群级别的ClusterRole。</p> </li><li> <p>Role、RoleBinding、ClusterRole和ClusterRoleBinding 的关系如图 所示 。</p> </li><li> <p>一个命名空间中可以包含多个Role和RoleBinding对象，类似地，集群级别也可以同时存在多个ClusterRole和ClusterRoleBinding对 象。而一个账户也可经由RoleBinding ClusterRoleBinding关联至多个角色，从而具有多重许可授权。</p> </li></ul> 
<p>下面我们来创建一个User Account，测试访问某些我们授权的资源：</p> 
<h3><a id="k8s_User_Account_84"></a>创建k8s User Account</h3> 
<h4><a id="_86"></a>一、创建证书</h4> 
<h5><a id="user_88"></a>创建user私钥</h5> 
<pre><code>[root@node-01 ~]# cd /etc/kubernetes/pki/
[root@node-01 pki]# (umask 077;openssl genrsa -out jenkins.key 2048)
Generating RSA private key, 2048 bit long modulus
.................................................................................+++
..................+++
e is 65537 (0x10001)
</code></pre> 
<h5><a id="_99"></a>创建证书签署请求</h5> 
<p>O=组织信息，CN=用户名</p> 
<pre><code>[root@node-01 pki]# openssl req -new -key jenkins.key -out jenkins.csr -subj "/O=jbt/CN=jenkins"
</code></pre> 
<h5><a id="_108"></a>签署证书</h5> 
<pre><code>[root@node-01 pki]# openssl  x509 -req -in jenkins.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out jenkins.crt -days 365
Signature ok
subject=/O=jbt/CN=jenkins
Getting CA Private Key
</code></pre> 
<h4><a id="_118"></a>二、创建配置文件</h4> 
<p>创建配置文件主要有以下几个步骤：</p> 
<pre><code>kubectl config set-cluster --kubeconfig=/PATH/TO/SOMEFILE      #集群配置
kubectl config set-credentials NAME --kubeconfig=/PATH/TO/SOMEFILE #用户配置
kubectl config set-context    #context配置
kubectl config use-context    #切换context
</code></pre> 
<blockquote> 
 <p>–embed-certs=true的作用是不在配置文件中显示证书信息。<br> –kubeconfig=/root/jenkins.conf 用于创建新的配置文件，如果不加此选项,则内容会添加到家目录下.kube/config文件中，可以使用use-context来切换不同的用户管理k8s集群。可以不加<br> context简单的理解就是用什么用户来管理哪个集群，即用户和集群的结合。</p> 
</blockquote> 
<h5><a id="_135"></a>创建集群配置</h5> 
<pre><code>[root@node-01 pki]# kubectl config set-cluster k8s --server=https://10.31.90.200:8443 --certificate-authority=ca.crt --embed-certs=true --kubeconfig=/root/jenkins.conf
Cluster "k8s" set.

## 文件  /root/jenkins.conf 内容
[root@node-01 pki]# kubectl config view --kubeconfig=/root/jenkins.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []
</code></pre> 
<h5><a id="_156"></a>创建用户配置</h5> 
<pre><code>[root@node-01 pki]# kubectl config set-credentials jenkins --client-certificate=jenkins.crt --client-key=jenkins.key --embed-certs=true --kubeconfig=/root/jenkins.conf
User "jenkins" set.

#查看配置文件 /root/jenkins.conf
[root@node-01 pki]# kubectl config view --kubeconfig=/root/jenkins.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: jenkins
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
</code></pre> 
<h5><a id="context_181"></a>创建context配置</h5> 
<pre><code>[root@node-01 pki]# kubectl config set-context jenkins@k8s --cluster=k8s --user=jenkins --kubeconfig=/root/jenkins.conf
Context "jenkins@k8s" created.

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/jenkins.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: jenkins
  name: jenkins@k8s
current-context: ""
kind: Config
preferences: {}
users:
- name: jenkins
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
</code></pre> 
<h5><a id="context_210"></a>切换context</h5> 
<pre><code>[root@node-01 pki]# kubectl config use-context jenkins@k8s --kubeconfig=/root/jenkins.conf
Switched to context "jenkins@k8s".

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/jenkins.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: jenkins
  name: jenkins@k8s
current-context: jenkins@k8s
kind: Config
preferences: {}
users:
- name: jenkins
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
</code></pre> 
<h5><a id="rootjenkinsconf_239"></a>最终效果生成配置文件（/root/jenkins.conf）</h5> 
<pre><code>apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS***Cg==
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: jenkins
  name: jenkins@k8s
current-context: jenkins@k8s
kind: Config
preferences: {}
users:
- name: jenkins
  user:
    client-certificate-data: LS0tLS1C***S0K
    client-key-data: LS0tLS1CR***RVktLS0tLQo=
</code></pre> 
<blockquote> 
 <p>这就是 kubectl 命令的配置文件了，其中 current-context 配置。就是<code>kubectl config use-context</code>切换之后的配置了.如果一开始就不加 <code>--kubeconfig=/root/jenkins.conf</code>这里将是两个用户。一个是以前的老用户，如下：</p> 
</blockquote> 
<pre><code>apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJ***0tLS0tCg==
    server: https://10.31.90.200:8443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: jenkins
  name: jenkins@k8s
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: jenkins@k8s
kind: Config
preferences: {}
users:
- name: jenkins
  user:
    client-certificate-data: LS0tLS1CRUdJ***FUK
    client-key-data: LS0tLS1CRUdJ***SBLRVktLS0tLQo=
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiB***FURS0tLS0tCg==
    client-key-data: LS0tLS1CU***0tLQo=

</code></pre> 
<h5><a id="k8s_296"></a>创建系统用户及k8s验证文件</h5> 
<pre><code>[root@node-01 ~]# useradd jenkins     #创建什么用户名都可以
[root@node-01 ~]# mkdir /home/jenkins/.kube
[root@node-01 ~]# cp jenkins.conf /home/jenkins/.kube/config
[root@node-01 ~]# chown jenkins.jenkins -R /home/jenkins/.kube/
[root@node-01 ~]# su - jenkins
[jenkins@node-01 ~]$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "jenkins" cannot list resource "pods" in API group "" in the namespace "default"
#默认新用户是没有任何权限的。
</code></pre> 
<h4><a id="_309"></a>绑定角色</h4> 
<h5><a id="Role_311"></a>创建Role</h5> 
<p>此role只有pod的get、list、watch权限</p> 
<pre><code>[root@node-01 rbac]# cat pods-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pods-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

[root@node-01 rbac]# kubectl apply -f pods-reader.yaml 
role.rbac.authorization.k8s.io/pods-reader created
</code></pre> 
<h5><a id="Rolebinding_335"></a>创建Rolebinding</h5> 
<p>用户jenkins和role pods-reader的绑定</p> 
<pre><code>[root@node-01 rbac]# cat jenkins-pods-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jenkins-pods-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: jenkins
  
  
[root@node-01 rbac]# kubectl apply -f jenkins-pods-reader.yaml 
rolebinding.rbac.authorization.k8s.io/jenkins-pods-reader created
</code></pre> 
<h5><a id="_359"></a>验证结果</h5> 
<p>如果没有指定命名空间的话，默认就是default命名空间。</p> 
<pre><code>[jenkins@node-01 ~]$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
nginx-demo-95bd675d5-66xrm   1/1     Running   0          18d
tomcat-5c5dcbc885-7vr68      1/1     Running   0          18d


[jenkins@node-01 ~]$ kubectl -n kube-system get pod
Error from server (Forbidden): pods is forbidden: User "jenkins" cannot list resource "pods" in API group "" in the namespace "kube-system"
</code></pre> 
<p>所以我们是可以查看查看default命名空间的pod，但是其他空间的pod是无法查看的。</p> 
<h5><a id="ClusterRole_376"></a>创建ClusterRole</h5> 
<pre><code>[root@node-01 rbac]# cat cluster-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
  

[root@node-01 rbac]# kubectl apply -f cluster-reader.yaml 
clusterrole.rbac.authorization.k8s.io/cluster-reader created
</code></pre> 
<h5><a id="ClusterRoleBinding_399"></a>创建ClusterRoleBinding</h5> 
<pre><code>[root@node-01 rbac]# cat jenkins-read-all-pods.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: jenkins-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: jenkins
  
  
[root@node-01 rbac]# kubectl apply -f jenkins-read-all-pods.yaml 
clusterrolebinding.rbac.authorization.k8s.io/jenkins-read-all-pods created
</code></pre> 
<h5><a id="_421"></a>验证结果</h5> 
<p>创建了ClusterRole和ClusterRoleBinding后就可以看到所有命名空间的pod了。</p> 
<pre><code>[jenkins@node-01 ~]$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
nginx-demo-95bd675d5-66xrm   1/1     Running   0          18d
tomcat-5c5dcbc885-7vr68      1/1     Running   0          18d

[jenkins@node-01 ~]$ kubectl -n kube-system get pod
NAME                                        READY   STATUS    RESTARTS   AGE
canal-gd4qn                                 2/2     Running   0          21d
cert-manager-6464494858-wqpnb               1/1     Running   0          18d
coredns-7f65654f74-89x69                    1/1     Running   0          18d
coredns-7f65654f74-bznrl                    1/1     Running   2          54d
...
</code></pre>
                </div>
            </body>
            </html>
            